<template>
	<div>
		<div class="swaps">
			<div class="swapinputbox">
				<el-icon @click="tokenswitch" class="swapicon">
					<Sort />
				</el-icon>
				<div class="dsiv">
					<div class="balance">余额:{{ tokenabalance }}</div>
					<div class="transaction">
						<el-input disabled v-model="tokenaquantity" placeholder="请输入兑换数量" />
						<div class="swapinput">
							<el-avatar class="tokenlistlogo" size="small" :src="tokena ? 'https://webgallery.oss-cn-beijing.aliyuncs.com/token/' + chain + '/' + tokena.toLowerCase() + '.png' : ''" />
							<el-select :disabled="disabled" @change="Checkbalances" v-model="tokena" class="m-2" placeholder="选择代币" size="large">
								<el-option v-for="(item, index) in tokenlista" :key="index" :label="item.name.toUpperCase()" :value="item.address" :disabled="item.address == tokenb ? true : false">
									<div class="tookenlist">
										<el-avatar size="small" :src="item.address ? 'https://webgallery.oss-cn-beijing.aliyuncs.com/token/' + chain + '/' + item.address.toLowerCase() + '.png' : ''" />
										<span>{{ item.name.toUpperCase() }}</span>
									</div>
								</el-option>
							</el-select>
						</div>
					</div>
				</div>
				<div class="dsiv">
					<div class="balance">余额:{{ tokenbbalance }}</div>
					<div class="transaction">
						<el-input disabled v-model="tokenbquantity" placeholder="请输入兑换数量" />
						<div class="swapinput">
							<el-avatar size="small" :src="tokenb ? 'https://webgallery.oss-cn-beijing.aliyuncs.com/token/' + chain + '/' + tokenb.toLowerCase() + '.png' : ''" />
							<el-select :disabled="disabled" @change="Checkbalances" v-model="tokenb" class="m-2" placeholder="选择代币" size="large">
								<el-option v-for="(item, index) in tokenlista" :key="index" :label="item.name.toUpperCase()" :value="item.address" :disabled="item.address == tokena ? true : false">
									<div class="tookenlist">
										<el-avatar size="small" :src="item.address ? 'https://webgallery.oss-cn-beijing.aliyuncs.com/token/' + chain + '/' + item.address.toLowerCase() + '.png' : ''" />
										<span>{{ item.name.toUpperCase() }}</span>
									</div>
								</el-option>
							</el-select>
						</div>
					</div>
				</div>
			</div>
			<div class="Settings">
				<div class="Settings"
					><el-tag :type="Proportion == 0.25 ? 'danger' : ''" @click=";(Proportion = 0.25), getExchangequantity()">25%</el-tag>
					<el-tag :type="Proportion == 0.5 ? 'danger' : ''" @click=";(Proportion = 0.5), getExchangequantity()">50%</el-tag>
					<el-tag :type="Proportion == 1 ? 'danger' : ''" @click=";(Proportion = 1), getExchangequantity()">100%</el-tag>
					<el-input style="width: 100px; height: 24px" size="small" placeholder="请输入数量" @input="getlp" v-model="Exchangequantity"> </el-input
				></div>

				<el-icon class="Settingsicon" @click="dialogVisible = true">
					<Tools />
				</el-icon>
			</div>
			<!-- tokena 或者tokenB  -->
			<!-- 余额不足 -->
			<!-- 未授权 -->
			<el-button v-if="!lpaddress" class="swapbutton" :disabled="true" type="primary">余额不足</el-button>
			<el-button v-else-if="!Authorizeornot" :disabled="disabled" class="swapbutton" :loading="loading" type="primary" @click="Authorize()">approve</el-button>
			<el-button v-else class="swapbutton" :loading="loading" :disabled="disabled" type="primary" @click="trade">交易</el-button>
		</div>
		<el-dialog class="dialog" v-model="dialogVisible" title="设置" width="350px">
			<el-form :model="form" label-position="top" label-width="50px">
				<el-form-item>
					<template #label>
						<div class="label">
							<span>滑点上限</span>
							<el-tooltip effect="dark" content="Top Left prompts info" placement="top-start">
								<el-icon>
									<InfoFilled />
								</el-icon>
							</el-tooltip>
						</div>
					</template>
					<el-check-tag :checked="form.Slippage == 0.1" style="margin-right: 8px" @click="form.Slippage = 0.1">0.1%</el-check-tag>
					<el-check-tag :checked="form.Slippage == 0.5" style="margin-right: 8px" @click="form.Slippage = 0.5">0.5%</el-check-tag>
					<el-check-tag :checked="form.Slippage == 1" style="margin-right: 8px" @click="form.Slippage = 1">1.0%</el-check-tag>
					<el-input style="width: 80px" v-model="form.Slippage" placeholder="Please input">
						<template #append>%</template>
					</el-input>
					<!-- <el-input @input="Contentedited" v-model="form.title" /> -->
				</el-form-item>
			</el-form>
			<el-form :model="form">
				<el-form-item>
					<template #label>
						<div class="label">
							<span>专家模式</span>
							<el-tooltip effect="dark" content="绕过确认模式并允许高滑点交易。使用风险自负。" placement="top-start">
								<el-icon>
									<InfoFilled />
								</el-icon>
							</el-tooltip>
						</div>
					</template>
					<el-switch v-model="form.expert" />
					<!-- <el-input @input="Contentedited" v-model="form.title" /> -->
				</el-form-item>
			</el-form>
		</el-dialog>
	</div>
</template>
<script>
	import { dataRequest as api, truncateDecimal, Checkethbalance, Checktokenbalance, getprovider } from '@/api/api'
	import { mapState } from 'vuex'
	import { ethers } from 'ethers'
	import Decimal from 'decimal.js'
	export default {
		components: {},
		computed: {
			...mapState(['address', 'chain', 'balance']),
		},
		props: ['data'],
		data() {
			return {
				Proportion: '1',
				Exchangequantity: '0',
				dialogVisible: false,
				tokenaname: '',
				tokenbname: '',
				Authorizeaddress: '',
				path: [],
				Authorizeornot: false,
				loading: false,
				disabled: false,
				tokenlista: [],
				tokenlist: [],
				tokenaquantity: '0',
				tokenbquantity: '0',
				tokena: '',
				tokenb: '',
				tokenabalance: 0,
				tokenbbalance: 0,
				tokenadecimals: 0,
				tokenbdecimals: 0,
				form: {
					Slippage: 0.5,
					expert: false,
				},
				Factory: null,
				PancakeRouter: null,
				contract: null,
				tokenarate: 0,
				tokenbrate: 0,
				lpbalance: 0,
				lpaddress: null,
			}
		},
		methods: {
			tokenswitch() {
				;[this.tokena, this.tokenb] = [this.tokenb, this.tokena]
				this.Checkbalances()
			},
			// 要在这里获取默认的链
			async getdata() {
				try {
					let arr = await api('Query', 'tokenlist', { chain: this.chain })
					if (arr.code == 200) {
						this.tokenlist = [...arr.data]
						this.tokenlista = [...arr.data]
						// 如果是默认链 就不能使用下面的
						if (this.chain == this.data.swap.chanid && this.data.swap.tokena && this.data.swap.tokenb) {
							// 链ID  和默认ID 相同  且存在交易对
							// 要先检查  这个代币  必须是不存在的

							if (!this.tokenlist.some((obj) => obj.address.toLowerCase() == this.data.swap.tokena.toLowerCase())) {
								let tokenjson = await this.tokenname(this.data.swap.tokena)
								if (tokenjson) {
									this.tokenlista.push(tokenjson)
									this.tokenlist.push(tokenjson)
								}
							}
							if (!this.tokenlist.some((obj) => obj.address.toLowerCase() == this.data.swap.tokenb.toLowerCase())) {
								let tokenjson = await this.tokenname(this.data.swap.tokenb)
								if (tokenjson) {
									this.tokenlista.push(tokenjson)
									this.tokenlist.push(tokenjson)
								}
							}
							this.tokena = this.data.swap.tokena
							this.tokenb = this.data.swap.tokenb
						} else {
							this.tokena = arr.data[1].address
							this.tokenb = arr.data[0].address
						}

						if (this.address) {
							// 还要获取当前链的信息
							this.getchain()
							this.Checkbalances()
						}
						this.disabled = false
					} else {
						this.disabled = true
						//提示不支持此链  切换到默认链
						// 否则会报错的
						// this.tokenlist = []
						// this.tokenlista = []
					}
				} catch (error) {
					if (error.info && error.info.error) {
						const errorMessage = error.info.error.data && error.info.error.data.message ? error.info.error.data.message : error.info.error.message

						this.$message.error(errorMessage)
					} else {
						this.$message.error('Error message not available')
					}
				}
			},
			async getchain() {
				try {
					let arr = await api('Query', 'chain', this.chain)

					if (arr.code == 200) {
						this.Factory = arr.data.Factory
						this.PancakeRouter = arr.data.PancakeRouter
						this.contract = arr.data.contract
					}
				} catch (error) {
					console.error(error)
				}
			},
			async select(query) {
				// 搜索名称  还要不等于第一个仓库的数据
				if (query.length < 42) {
					let tokenlist = this.tokenlist.slice()
					this.tokenlista = tokenlist.filter((item) => {
						return item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 || item.address.toLowerCase().indexOf(query.toLowerCase()) > -1
					})
				} else if (query.length == 42) {
					if (!this.tokenlist.some((obj) => obj.address.toLowerCase() == query.toLowerCase())) {
						let tokenjson = await this.tokenname(query)
						if (tokenjson) {
							this.tokenlista = [tokenjson]
							this.tokenlist.push(tokenjson)
						}
					} else {
						let tokenlist = this.tokenlist.slice()
						this.tokenlista = tokenlist.filter((item) => {
							return item.name.toLowerCase().indexOf(query.toLowerCase()) > -1 || item.address.toLowerCase().indexOf(query.toLowerCase()) > -1
						})
					}
					// 通过代币地址查询
					// 这里要使用合约查询
					//查询代币名称  然后返回
				} else {
					this.$message.error('代币地址长度错误')
					this.tokenlista = this.tokenlist.slice()
				}
			},
			// 查询代币名称
			async tokenname(query) {
				try {
					// 需要获取代币名称

					let abi = ['function symbol() external view returns (string memory)']
					let contract = new ethers.Contract(query, abi, getprovider())
					let name = await contract.symbol()
					return { chain: this.chain, address: query, name: name, eth: '0' }
				} catch (error) {
					this.$message.error('代币地址错误')
					this.tokenlista = this.tokenlist.slice()
					return false
				}

				// this.loading = false
			},
			// 查询余额
			// 交易
			//  token 需要授权
			// 检查tokena 如果是代币  就检查授权数量  如果授权数量小于交易数量  显示授权  授权足够 就显示交易
			// 这里判断代币AB
			async Checkbalances() {
				// 查询余额
				// 先要判断是不是bnb
				// 这里貌似无限重复
				// 这里设置两个代币名称
				try {
					for (let i = 0; i < this.tokenlist.length; i++) {
						if (this.tokena == this.tokenlist[i].address) {
							this.tokenaname = this.tokenlist[i].name
							if (this.tokenlist[i].eth == '1') {
								this.tokenabalance = truncateDecimal(await Checkethbalance(this.address))
							} else {
								this.tokenabalance = truncateDecimal(await Checktokenbalance(this.address, this.tokena))
							}
						}

						if (this.tokenb == this.tokenlist[i].address) {
							this.tokenbname = this.tokenlist[i].name
							if (this.tokenlist[i].eth == '1') {
								this.tokenbbalance = truncateDecimal(await Checkethbalance(this.address))
							} else {
								this.tokenbbalance = truncateDecimal(await Checktokenbalance(this.address, this.tokenb))
							}
						}
					}
					// 这里哪里代币A和代币B  获取交易对
					if (this.tokena && this.tokenb) {
						this.getlp()
					}

					// this.isAuthorize()
				} catch (error) {
					console.error(error)
				}

				// 检查授权
			},
			getExchangequantity() {
				// 计算金额
				if (this.lpbalance > 0) {
					this.Exchangequantity = new Decimal(this.lpbalance).mul(new Decimal(this.Proportion)).toFixed(5)
					this.getlp()
				}
			},
			// 获取LP  并且计算单价
			async getlp() {
				let abi = ['function getPair(address tokenA, address tokenB) view returns (address pair)']
				if (!this.Factory) {
					await this.getchain()
				}
				let contract = new ethers.Contract(this.Factory, abi, getprovider())
				let lpaddress = await contract.getPair(this.tokena, this.tokenb)
				if (lpaddress != '0x0000000000000000000000000000000000000000') {
					// 计算数量
					let abi = ['function totalSupply() external view returns (uint)', 'function token0() external view returns (address)', 'function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)']
					let contract = new ethers.Contract(lpaddress, abi, getprovider())
					let tokena = await contract.token0()
					let getReserves = await contract.getReserves()
					let totalSupply = ethers.formatUnits(await contract.totalSupply())
					abi = ['function rate() public view returns (uint)', 'function getLiquidity(address tokenA,address tokenB,uint amountADesired,address swapV2Router) public view returns (uint)', 'function getaost(address[] calldata _path,uint256 _autom,address _addr,address[] calldata circulation) public view returns (uint256, address[] memory, string[] memory)', 'function decimals() view returns (uint8)']
					contract = new ethers.Contract(this.tokena, abi, getprovider())
					this.tokenadecimals = await contract.decimals()
					contract = new ethers.Contract(this.tokenb, abi, getprovider())
					this.tokenbdecimals = await contract.decimals()
					this.lpbalance = truncateDecimal(await Checktokenbalance(this.address, lpaddress))
					// 获取到了总量
					if (this.Exchangequantity == 0 || this.lpbalance > 0) {
						this.Exchangequantity = new Decimal(this.lpbalance).mul(new Decimal(this.Proportion)).toFixed(5)
					}
					// 计算一下比例

					if (this.tokena == tokena) {
						this.tokenarate = new Decimal(ethers.formatUnits(getReserves[0], this.tokenadecimals)).div(new Decimal(totalSupply.toString())).toString()
						this.tokenbrate = new Decimal(ethers.formatUnits(getReserves[1], this.tokenbdecimals)).div(new Decimal(totalSupply.toString())).toString()
						this.tokenaquantity = new Decimal(this.tokenarate).mul(new Decimal(this.Exchangequantity)).toFixed(5)
						this.tokenbquantity = new Decimal(this.tokenbrate).mul(new Decimal(this.Exchangequantity)).toFixed(5)
						// 		tokenadecimals: 0,
						// tokenbdecimals: 0,
						// 		tokenarate: 0,
						// tokenbrate: 0,
					} else {
						this.tokenarate = new Decimal(ethers.formatUnits(getReserves[1], this.tokenbdecimals)).div(new Decimal(totalSupply.toString())).toString()
						this.tokenbrate = new Decimal(ethers.formatUnits(getReserves[0], this.tokenadecimals)).div(new Decimal(totalSupply.toString())).toString()
						this.tokenaquantity = new Decimal(this.tokenarate).mul(new Decimal(this.Exchangequantity)).toFixed(5)
						this.tokenbquantity = new Decimal(this.tokenbrate).mul(new Decimal(this.Exchangequantity)).toFixed(5)
					}

					this.lpaddress = lpaddress
					this.isAuthorize()
					// 检查授权
				} else {
					this.lpaddress = null
				}
				// let abi = ['function decimals() view returns (uint8)', ' function allowance(address owner,address spender) external view returns (uint256)']
			},

			// 只要授权
			// 检查授权
			async isAuthorize() {
				try {
					// 先要判断是不是bnb

					// 这个要第一个input 输入了数字 才触发
					let abi = ['function decimals() view returns (uint8)', ' function allowance(address owner,address spender) external view returns (uint256)']
					let contract = new ethers.Contract(this.lpaddress, abi, getprovider())
					let allowance = await contract.allowance(this.address, this.PancakeRouter)
					// 获取当前代币精度
					let decimals = await contract.decimals()
					let balanceOf = ethers.formatUnits(allowance, decimals)

					if (balanceOf / 1 >= this.Exchangequantity / 1) {
						// 无需授权
						this.Authorizeornot = true
					} else {
						// 需要授权
						this.Authorizeornot = false
					}
				} catch (error) {
					if (error.info && error.info.error) {
						const errorMessage = error.info.error.data && error.info.error.data.message ? error.info.error.data.message : error.info.error.message

						this.$message.error(errorMessage)
					} else {
						this.$message.error('Error message not available')
					}
				}
			},
			// 授权
			async Authorize() {
				try {
					this.loading = true
					let abi = ['function approve(address spender, uint256 amount) external returns (bool)']
					let contract = new ethers.Contract(this.lpaddress, abi, await getprovider().getSigner())
					let tx = await contract.approve(this.PancakeRouter, ethers.MaxUint256)
					await tx.wait()
					this.loading = false
					this.isAuthorize()
				} catch (error) {
					this.loading = false
					if (error.info && error.info.error) {
						const errorMessage = error.info.error.data && error.info.error.data.message ? error.info.error.data.message : error.info.error.message

						this.$message.error(errorMessage)
					} else {
						this.$message.error('Error message not available')
					}
				}
			},

			// 交易
			async trade() {
				// 这里需要判断的是  第一个是不是ETH
				// 是就传入value
				// 不是就不传
				// this.$message.success(`保存成功`)
				// 还要判断是否余额不足
				if (!this.address) {
					this.$message.error(this.$t('message.Pleaselinkwallet'))
					return
				}
				if (this.Exchangequantity <= 0) {
					this.$message.error('请输入添加数量')
					return
				}

				try {
					this.loading = true
					let continuei = false
					let abi = ['function removeLiquidity(address tokenA, address tokenB,uint liquidity,uint amountAMin,uint amountBMin,address to, uint deadline)', 'function removeLiquidityETH(address token,uint liquidity,uint amountTokenMin,uint amountETHMin,address to,uint deadline)']
					let contract = new ethers.Contract(this.PancakeRouter, abi, await getprovider().getSigner())
					// 计算代币A最小数量
					let amountAMin = new Decimal(this.tokenaquantity.toString()).sub(new Decimal(this.tokenaquantity.toString()).mul(new Decimal(this.form.Slippage.toString()).div('100'))).toFixed(parseInt(this.tokenadecimals))
					amountAMin = ethers.parseUnits(amountAMin, this.tokenadecimals)
					// 计算代币B最小数量
					let amountBMin = new Decimal(this.tokenbquantity.toString()).sub(new Decimal(this.tokenbquantity.toString()).mul(new Decimal(this.form.Slippage.toString()).div('100'))).toFixed(parseInt(this.tokenbdecimals))
					amountBMin = ethers.parseUnits(amountBMin, this.tokenbdecimals)
					for (let i = 0; i < this.tokenlist.length; i++) {
						// tokena
						if (this.tokena == this.tokenlist[i].address && this.tokenlist[i].eth == '1') {
							continuei = true
							//tokena是 ETH
							let tx = await contract.removeLiquidityETH(this.tokenb, ethers.parseUnits(this.Exchangequantity), amountBMin, amountAMin, this.address, Math.floor(Date.now() / 1000) + 100)
							await tx.wait()
							this.$message.success(this.$t('message.Transactionsuccessful'))
						} else if (this.tokenb == this.tokenlist[i].address && this.tokenlist[i].eth == '1') {
							//tokenb ETH
							continuei = true
							let tx = await contract.removeLiquidityETH(this.tokena, ethers.parseUnits(this.Exchangequantity), amountAMin, amountBMin, this.address, Math.floor(Date.now() / 1000) + 100)
							await tx.wait()
							this.$message.success(this.$t('message.Transactionsuccessful'))
						}
					}
					// 在这里处理不是eth的情况
					if (!continuei) {
						let tx = await contract.removeLiquidity(this.tokena, this.tokenb, ethers.parseUnits(this.Exchangequantity), amountAMin, amountBMin, this.address, Math.floor(Date.now() / 1000) + 100)
						await tx.wait()
						this.$message.success(this.$t('message.Transactionsuccessful'))
					}

					this.loading = false
				} catch (error) {
					console.error(error)
					if (error.info && error.info.error) {
						const errorMessage = error.info.error.data && error.info.error.data.message ? error.info.error.data.message : error.info.error.message

						this.$message.error(errorMessage)
					} else {
						this.$message.error('Error message not available')
					}
					this.loading = false
				}
			},
		},
		mounted() {
			this.getdata()
		},
		watch: {
			address(newContent, oldContent) {
				if (newContent) {
					this.Checkbalances()
				}
			},
			chain(newContent, oldContent) {
				if (newContent) {
					this.getdata()
				}
			},
		},
	}
</script>
<style>
	.tookenlist .el-avatar--small {
		--el-avatar-size: 20px !important;
	}
	.tookenlist {
		display: flex;
		flex-direction: row;
		gap: 10px;
		align-items: center; /* 垂直居中 */
	}
	.dialog .label {
		display: flex;
		flex-direction: row;
		font-size: 16px;
		font-weight: bold;
		align-items: center; /* 垂直居中 */
		gap: 5px;
	}
	.dialog .el-input-group__append,
	.dialog .el-input-group__prepend {
		padding: 0 10px !important;
	}
	.dialog .el-dialog__body {
		padding: 10px 15px;
	}
	.swaps .swapinputbox {
		display: flex;
		flex-direction: column;
		position: relative;
		gap: 5px;
	}
	.swaps .swapinputbox .dsiv {
		border-radius: 4px;
		background: #f4f4f5;
		display: flex;
		flex-direction: column;
		gap: 5px;
	}
	.swaps .transaction {
		display: flex;
		/* flex-direction: row; */
	}
	.swaps .el-input__wrapper {
		box-shadow: none !important;
		background-color: #f4f4f5;
	}
	.swaps .el-select .el-input.is-focus .el-input__wrapper {
		box-shadow: none !important;
	}
	.swaps .el-select .el-input__wrapper.is-focus {
		box-shadow: none !important;
	}
	.swaps .is-focus {
		box-shadow: none !important;
	}
	.swaps .swapinput {
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}
	.swaps .el-input {
		width: 176px;
	}
	.swaps .swapinput .el-input {
		width: 120px;
	}
	.swaps .balance {
		padding: 5px 11px;
		font-size: 14px;
		color: #b1b3b8;
	}
	.swaps .swapicon {
		width: 20px;
		height: 20px;
		background: var(--el-color-primary);
		border-radius: 50%;
		color: #fff;
		font-size: 16px;
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		right: 5px;
		z-index: 2;
	}
	.swaps .swapbutton {
		width: 100%;
	}
</style>
<style scoped>
	.swaps {
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		gap: 15px;
	}
	.Settings {
		height: 20px;
		width: 100%;
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
		gap: 10px;
	}

	.Settingsicon {
		font-size: 20px;
		color: #606266;
	}
</style>
